package org.supda.system.task;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.hyperic.sigar.Cpu;
import org.hyperic.sigar.CpuPerc;
import org.hyperic.sigar.Mem;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.supda.system.controller.vo.Data;
import org.supda.system.entity.TServerWarnProperties;
import org.supda.system.entity.TUser;
import org.supda.system.entity.system.ActualEntity;
import org.supda.system.service.TMessageService;
import org.supda.system.service.TServerWarnPropertiesService;

/**
 * 定时任务
 * @author supda
 * @Date 2017-2-27 下午3:58:34
 *
 * Spring @Scheduled是Spring计划任务的一种很简洁的实现。用来替代Quartz的方案。
 */
@Service
@Lazy(false) 
public class ScheduledTasks{
	
		//此处无法使用注解,BUG？
		public  static SimpMessageSendingOperations simpMessageSendingOperations;
		
		@Autowired private TServerWarnPropertiesService warnPropertiesService;
		
		@Autowired private TMessageService messageService;
		
		//缓存历史数据，取平局值，用于判断是否超标
		private static List< ActualEntity > aes = new ArrayList<ActualEntity>();
		
		DecimalFormat df = new DecimalFormat("#.000");
		
		Random random = new Random();
		
		//告警信息记录的检查次数，默认为10次
		private static short checkTimes = 10;
		
		//计数器
		private static int checkCount = 0;
		
	    private static Sigar sigar;  
		
	    public static Sigar getInstance() {  
	        if (null == sigar) {  
	            sigar = new Sigar();  
	        }  
	        return sigar;  
	    }  
	    
	    ActualEntity ae = new ActualEntity();
		
		//运行时数据获取
		Runtime runtime = Runtime.getRuntime();  
	
	    @Scheduled(cron="0/1 * *  * * ? ")   //每2秒执行一次   
	    public void trigger() {
	       try { 	   	
	    	    //获取最新的系统数据
				this.getActualEntity(ae);
		
		        if(simpMessageSendingOperations != null && ae!=null ){
		        	//发送实时数据
		        	simpMessageSendingOperations.convertAndSend("/topic/actual", ae);
		        }
		        
		        aes.add(ae);
		    	
		    	//判段checkCount是否达到校验
	    	   if(checkTimes !=0 && checkCount >= checkTimes){
	    		   
	    		   	//每checkTimes*space检查配置情况
	    		   
			    	//取最新配置
			    	TServerWarnProperties serverWarnProperties = warnPropertiesService.getLastWarnProperties();
			    	
			    	if(serverWarnProperties !=null)
			    	{	
			    		//配置更新
			    		if(!serverWarnProperties.getCheckTimes().equals(checkTimes)){
			    			//重置checkTimes和checkCount,移除所有缓存元素。
			    			checkCount = 0;
				    		checkTimes = serverWarnProperties.getCheckTimes();
				    		aes.clear();
			    		}
			    	}
	    		   
	    		   String content =  judgeToPersistent(serverWarnProperties);
	    	   
	    		   //超标入库
	    		   if( !StringUtils.isEmpty(content)) {
	    			   messageService.save(content , 3 , serverWarnProperties.getTRole().getId(), "系统", Short.parseShort("3"));//默认失败重试3次
	    		   }
	    		   //重置checkCount和aes
	    		   checkCount = -1;
	    		   aes.clear();
	    	   }

			} catch (SigarException e) {
				checkCount = -1;
				aes.clear();
			}
	       
	       checkCount ++;
	    }
	    
	    //判断是否超过warn设定值
	    private String judgeToPersistent(TServerWarnProperties serverWarnProperties) {

	    	if(aes.size()==0) return null;
	    	
	    	double CpuUsage= 0;
	    	double JVMMemoryUsage = 0;
	    	double MemoryUsage = 0;
	    	
	    	for(int i =0 ; i < aes.size() ; i++){
	    		ActualEntity ae = aes.get(i);
	    		
	    		CpuUsage += Double.parseDouble(ae.getCpuUsage())/aes.size();
	    		JVMMemoryUsage += Double.parseDouble(ae.getJVMMemoryUsage())/aes.size();
	    		MemoryUsage += Double.parseDouble(ae.getMemoryUsage())/aes.size();
	    	}
	    	
	    	if(CpuUsage >serverWarnProperties.getCpuWarn()
	    	||JVMMemoryUsage>serverWarnProperties.getJvmWarn()
	    	||MemoryUsage > serverWarnProperties.getMemoryWarn()){
	    		
	    		return "服务器警告！CPU使用率="+df.format(CpuUsage)
	    				+"%, 内存使用率="+df.format(MemoryUsage)
	    				+"%, JVM内存占用="+df.format(JVMMemoryUsage)+"%";
	    	}
	    	return null;
		}


		public void getActualEntity(ActualEntity ae) throws SigarException{
	    	CpuPerc cp = getInstance().getCpuPerc();
	    	
	    	Mem mem = getInstance().getMem();
	    	
	    	ae.setCpuUsage(cp.getCombined()*100+"");
	    	ae.setMemoryUsage((1.000*mem.getUsed()/mem.getTotal()*100)+"");
	    	
	    	long totalMemory = runtime.totalMemory();
	    	long freeMemory = runtime.freeMemory();
	    	ae.setJVMMemoryUsage((1.000-1.000*freeMemory/totalMemory)*100.00+"");   	
	    }
		
		
	  /*  
	    private void warpToSystemInfo(TServerInfo serverInfo) throws SigarException{
	    	
	    	//运行时数据
	    	{
	    		serverInfo.setJvmAvailableProcessors(runtime.availableProcessors()+"");
	    		serverInfo.setJvmTotal(runtime.totalMemory()/(1024*1024)+"");//字节换算到M
	    		serverInfo.setJvmUsed(((runtime.totalMemory()-runtime.freeMemory())/(1024*1024)+""));//字节换算到M
	    	}
	    	
	    	//cpu信息
	    	Cpu cpu = sigar.getCpu();
	    	//cpu各状态百分比
	    	CpuPerc cp =sigar.getCpuPerc();
	    	
	    	//cpu数据
	    	serverInfo.setCpuTotal(cpu.getTotal()+"");
	    	serverInfo.setCpuUseRate(cp.getUser()+"");
	    	serverInfo.setCpuOsUseRate(cp.getSys()+"");
	    	serverInfo.setCpuWaitRate(cp.getWait()+"");
	    	serverInfo.setCpuTotalRate((cp.getSys()+cp.getUser())+"");
	    	serverInfo.setCpuFreeRate(cp.getIdle()+"");
	    	
	    	//内存信息
	    	 Mem memory = sigar.getMem();
	    	
	    	 serverInfo.setMemoryFree(memory.getFree()/(1024*1024)+"");
	    	 serverInfo.setMemoryTotal(memory.getTotal()/(1024*1024)+"");
	    	 serverInfo.setMemoryUsed(memory.getUsed()/(1024*1024)+"");
	    	 
	    	 //磁盘信息

	    }*/
	    
}
